#include "Game.h"

using namespace std;

Game::Game(std::vector<std::string> names) {
	std::vector<std::string>::iterator it = names.begin();
	while(it != names.end()) {
		Player* p = new Player(*it);
		players.push_back(p); //Create a vector element for all names
		it++;
	}
	deck = new Deck(); //Create a new deck
	house = new House("House", players, deck); //Create a new House with the initialized players
}


void Game::play() {
	house->DealFirstRound(); //Always start by dealing the first round
	printAllHands();

	
	//The house does not have 21, so start dealing more cards
	if(!playerHas21(house)) { 
		//Hit players which are active while not all players are finished
		while(!allPlayersFinished()) { 
			hitActivePlayers();
		}
	
		//If not all players are busted, deal cards to the house
		if(!allPlayersBusted()) { 

			//while the house has not reached 17, he must hit himself
			while(house->getTotal() < 17)  { 
				house->dealOneCardToItself();
				house->printHand();
				if(house->getTotal() > 21) //If he crossed 21, he is busted
					house->bust();
			}

			//If the house is not busted, then the hands of all active players must be compared with that of the house
			if(!house->isBusted()) {
				compareActivePlayersToHouse();
			} else { //The house is busted and loses!
				std::vector<Player *>::iterator it = players.begin();
				while(it != players.end()) { //All active players win!
					if(!(*it)->isBusted())
						cout << (*it)->getName() << " wins!"  << endl;
					it++;
				}
			}
		} else { //All Players are dead, house wins!
			std::vector<Player *>::iterator it = players.begin();
			while(it != players.end()) {
				cout << (*it)->getName() << " loses!"  << endl;
				it++;
			}
		}
	} else { //The house has 21 and wins!
		std::vector<Player *>::iterator it = players.begin();
		while(it != players.end()) {
			cout << (*it)->getName() << " loses!"  << endl;
			it++;
		}		
	}
}

void Game::printAllHands() {
	house->printHand();
	std::vector<Player *>::iterator it = players.begin();
	while(it != players.end()) {
		if(!(*it)->isBusted()) //If a player is not finished...
			(*it)->printHand(); //print its hand
		it++;
	}	
}

bool Game::allPlayersFinished() { 
	std::vector<Player *>::iterator it = players.begin();
	while(it != players.end()) {
		if(!playerIsFinished(*it)) //If a player is not finished...
			return false;	//Return false, since there is at least one player that is not finished
		it++;
	}	
	return true; //If the code reaches this line, all players are finished, so return true
}

bool Game::playerHas21(GenericPlayer *p) {
	if(p->getTotal() == 21) 
		return true;
	else 
		return false;
}

bool Game::playerIsFinished(GenericPlayer * p) {
	if(p->isBusted()|| !p->isHitting()) //If a player is busted or is not hitting, he is finished
		return true;
	else
		return false;
}

void Game::hitActivePlayers() {
	std::vector<Player *>::iterator it = players.begin();
	while(it != players.end()) {
		if(!(*it)->isBusted()) { //If a player is not busted
			house->askIfWantsOneCard(*it);
			if((*it)->isHitting()) {//And he wants a card
				house->dealOneCardToOnePlayer(*it); //deal him a card
				(*it)->printHand(); // Print this hand

				if((*it)->getTotal() > 21) {//If after dealing he has more than 21..
					(*it)->bust(); //He is busted!
				}
			}
		}
		it++;
	}
}

bool Game::allPlayersBusted() { 
	std::vector<Player *>::iterator it = players.begin();
	while(it != players.end()) {
		if(!(*it)->isBusted()) //If a player is not busted...
			return false;	//Return false, since there is at least one player that is not dead
		it++;
	}
	
	return true; //If the code reaches this line, all players are dead, so return true
}

void Game::compareActivePlayersToHouse() {
	std::vector<Player *>::iterator it = players.begin();
	while(it != players.end()) {
		if((*it)->getTotal() > house->getTotal()) //If a player has more points than the house, he wins
			cout << (*it)->getName() << " wins!"  << endl;
		else //Otherwise he loses (IN THE ACTUAL BLACK JACK GAME THERE ARE NO TIES, THE HOUSE WINS WITH EQUAL SCORE)
			cout << (*it)->getName() << " loses!"  << endl;
		it++;
	}
}